
package util.ui;

import java.math.BigDecimal;
import util.methods.Converters;
import util.methods.StringHelpers;

/**
 * A wrapper to get around the shortcomings of all of the Java float wrappers.
 * Sorts in natural (numeric) order but it's toString will round to a reasonable number
 * of decimal places
 * 
 */
public class DisplayFloat implements Comparable<DisplayFloat>
{
	
	static public int NUM_SIG_FIGS = 2;
	static public int NUM_DEC_PLACE = 2;
	static public int MODE = 1;
	
	static public int MODE_ROUND_DEC_PLUS_SIGFIGS = 1;
	static public int MODE_ROUND_DEC = 2;
	static public int MODE_ROUND_SIGFIGS = 3;
	static public int MODE_LEGACY_TRUNCATE = 4;
	static public int MODE_NOROUND = 5;
	
	public DisplayFloat ( Object inVal, double dMultiplier )
	{
		setValue ( inVal );
		d *= dMultiplier;
	}
	
	public DisplayFloat ( Object inVal )
	{
		setValue ( inVal );
	}
	public static void setDefaultMode()
	{
		setMode(MODE_ROUND_DEC_PLUS_SIGFIGS,2,2);
	}
	public static boolean isDefaulted()
	{
		return (MODE==1 && NUM_SIG_FIGS==2 && NUM_DEC_PLACE==2);
	}
	public static String getPrefString()
	{
		return MODE + "," + NUM_SIG_FIGS + "," + NUM_DEC_PLACE;
	}
	public static void setRoundingPrefs(String str)
	{
		if (str.trim().length()==0) return;
		String[] arr = str.trim().split(",");
		if (arr.length != 3)
		{
			System.err.println("Invalid rounding preferences:" + str);
			return;
		}
		try
		{
			MODE = Integer.parseInt(arr[0]);
			NUM_SIG_FIGS = Integer.parseInt(arr[1]);
			NUM_DEC_PLACE = Integer.parseInt(arr[2]);
			if (!isDefaulted())
			{
				setMode(MODE,NUM_SIG_FIGS,NUM_DEC_PLACE); // trigger message
			}
		}
		catch(Exception e)
		{
			System.err.println(e.getMessage());
			System.err.println("Invalid rounding preferences:" + str);
		}
	}
	public static void setMode(int mode, int sigfigs, int dec)
	{
		MODE = mode;
		NUM_SIG_FIGS = sigfigs;
		NUM_DEC_PLACE = dec;
		if (MODE == MODE_ROUND_DEC_PLUS_SIGFIGS)
		{
			//System.err.println("Rounding mode:" + NUM_DEC_PLACE + " decimal places, with minimum " + NUM_SIG_FIGS + " significant figures");
		}
		else if (MODE == MODE_ROUND_DEC)
		{
			//System.err.println("Rounding mode:" + NUM_DEC_PLACE + " decimal places");
		}
		else if (MODE == MODE_ROUND_SIGFIGS)
		{
			//System.err.println("Rounding mode:" + NUM_SIG_FIGS + " significant figures");
		}
		else if (MODE == MODE_LEGACY_TRUNCATE)
		{
			//System.err.println("Rounding mode: truncate to 2 decimal places, with minimum 2 significant figures");
		}
		else if (MODE == MODE_NOROUND)
		{
			//System.err.println("Rounding mode: no rounding");
		}
	}
	public static void setDigits(int sig, int dec)
	{
		NUM_SIG_FIGS = sig;
		NUM_DEC_PLACE = dec;		
	}
    public void add(double x)
    {
    	d += x;
    }
    
    public double div(double x)
    {
    	d /= x;
    	return d;
    }
	
	public void setValue ( double inVal ) { d = inVal; }
	
	public void setValue ( Object inVal ) 
	{ 
        if ( inVal instanceof BigDecimal )	
        {
            // Oracle uses these for floats.  Mostly annoying because they
            // "toString" w/o using scientific notation.
            BigDecimal bd = (BigDecimal)inVal;
            d = bd.doubleValue();
        } 
        else if ( inVal instanceof Integer )
        {
        	Integer i = (Integer)inVal;
        	d = i.doubleValue();
        }
        else if ( inVal instanceof Double )
        {
        	// In MySQL this seems to be the default the for MAX/MIN.
        	Double dbl = (Double)inVal;
        	d = dbl.doubleValue();
        }
        else if ( inVal instanceof Float )
        {
        	Float flt = (Float)inVal;
        	d = flt.doubleValue();             	                	
        }
        else if ( inVal instanceof String )
        {
        	String str = (String)inVal;
        	if (!StringHelpers.isEmpty(str)) 
        		d = Double.parseDouble( str );
        }
        else
        	throw new RuntimeException ( "Unexepected numeric type of " + inVal.getClass() );
	}
	
	public double getValue ( ) { return d; }
	
	
	public String toString ( ) 
	{
		if (MODE == MODE_ROUND_DEC_PLUS_SIGFIGS)
		{
			return Converters.roundBoth(d,NUM_SIG_FIGS,NUM_DEC_PLACE);
		}
		else if (MODE == MODE_ROUND_DEC)
		{
			return Converters.roundDec(d,NUM_DEC_PLACE);
		}
		else if (MODE == MODE_ROUND_SIGFIGS)
		{
			return Converters.roundToSigFigs(d,NUM_SIG_FIGS);
		}
		else if (MODE == MODE_LEGACY_TRUNCATE)
		{
			return Converters.decimalString(d, 2);
		}
		else if (MODE == MODE_NOROUND)
		{
			return new BigDecimal(d).toString();
		}
		System.err.println("Invalid float round mode:" + MODE);
		return  "";
	}
	
	
	public int compareTo ( DisplayFloat r )
	{
		DisplayFloat rNum = (DisplayFloat)r;
		return Double.compare( d, rNum.d );
	}
	
	private double d;
}
